Skip to content

RFC: Android Kotlin → Rust/Tauri 2 migration#96

Closed
hyperpolymath wants to merge 1 commit into
mainfrom
chore/tauri-migration-rfc
Closed

RFC: Android Kotlin → Rust/Tauri 2 migration#96
hyperpolymath wants to merge 1 commit into
mainfrom
chore/tauri-migration-rfc

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Status

DRAFT — RFC only. Awaiting owner review BEFORE any bulk conversion.
No Kotlin deleted, no Tauri scaffolding generated, no behaviour change.

Why

android/ ships 7 Kotlin files + 3 *.gradle.kts files, all banned by the
Hyperpolymath language policy. This keeps two CI gates permanently red:

  • Check for Banned Languages (.github/workflows/language-policy.yml:87-94)
  • governance / Language / package anti-pattern policy (estate-wide)

What this PR contains

A single document — docs/migrations/RFC-ANDROID-KOTLIN-TO-RUST.adoc — that:

  1. Inventories every Kotlin component (LoC, role, replacement).
  2. Names the unavoidable JVM-bytecode surfaceActivity, Service,
    BroadcastReceiver, AppWidgetProvider — that Android instantiates by
    class name and that pure Rust cannot satisfy.
  3. Proposes Path A (Tauri 2-generated Java shims under
    src-tauri/gen/android/, with a CI exemption analogous to
    node_modules/) and explicitly rejects Paths B (drop the widget) and
    C (JVM bytecode emission from Rust).
  4. Lays out a 9-PR landing sequence with explicit dependencies.

Component mapping (one-line summary)

Kotlin file Replacement
MainActivity.kt Tauri 2 MainActivity + AffineScript webview UI
NeurophoneService.kt Generated Java Service shim → JNI into Rust
BootReceiver.kt Generated Java BroadcastReceiver shim → JNI
NativeLib.kt Delete; lives in crates/neurophone-android/src/lib.rs
NeurophoneAppWidget.kt Generated Java AppWidgetProvider shim
NeurophoneWidgetActions.kt Generated Java BroadcastReceiver shim
NeurophoneWidgetConfigureActivity.kt Generated Java Activity shim (or drop)
*.gradle.kts Tauri-generated under gen/android/

Sub-PR sequence (proposed)

  1. This PR — RFC only.
  2. CI exemption for src-tauri/gen/android/ (coordinated with hyperpolymath/standards).
  3. cargo tauri android init scaffolding.
  4. Port NativeLib Kotlin → crates/neurophone-android/src/lib.rs.
  5. Port NeurophoneService.
  6. Port BootReceiver.
  7. Port widget triple (provider / actions / configure).
  8. AffineScript UI (replaces activity_main.xml).
  9. Delete legacy android/ tree — both CI gates green.

PRs 2 & 3 sequenced; 4–7 parallelizable after 3; 8 needs 4; 9 gated on all.

Open questions for owner

  1. Tauri vs Dioxus — RFC recommends Tauri 2; confirm.
  2. CI exemption scope — OK to exempt src-tauri/gen/android/?
  3. Estate governance — who owns the cross-repo anti-pattern policy
    callable in hyperpolymath/standards?
  4. Widget config sacrifice — acceptable to drop the configure activity?
  5. Hardware test plan — Oppo Reno 13 vs emulator + Termux?
  6. SPDX clash — repo files use PMPL-1.0-or-later, local hook expects
    MPL-2.0. Pick canonical before sub-PRs.

Constraints honoured in this PR

Test plan

  • RFC document renders as AsciiDoc.
  • Owner reviews component mapping for completeness.
  • Owner picks Tauri vs Dioxus, confirms CI-exemption plan, resolves SPDX clash.
  • Sub-PR Add STATE.scm project checkpoint file #2 (CI exemption) opens once approved.

🤖 Generated with Claude Code

Draft RFC for owner review before any bulk conversion. Maps each of the
7 Kotlin files + 3 *.gradle.kts to a Rust/Tauri replacement, calls out
the unavoidable JVM-bytecode surface (Service / BroadcastReceiver /
AppWidgetProvider), and proposes a 9-PR landing sequence gated on
CI-exemption coordination for Tauri-generated Java shims under
src-tauri/gen/android/.

No Kotlin deleted, no Tauri scaffolding generated — pure planning
artefact. Both banned-language CI gates remain red until the sequenced
sub-PRs land in order.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hyperpolymath

Copy link
Copy Markdown
Owner Author

Replaced by PR on chore/gossamer-migration-rfc — owner corrected the migration target from Tauri to Gossamer; rewriting under the right branch name.

@hyperpolymath
hyperpolymath deleted the chore/tauri-migration-rfc branch June 2, 2026 09:43

Copy link
Copy Markdown
Owner Author

Two owner decisions for this RFC are now settled — please update the doc accordingly before any sub-PRs:

  1. Framework: gossamer, not Tauri/Dioxus. The estate is standardising on hyperpolymath/gossamer — its own resource-safe Tauri/Electron replacement (Idris2 + Zig, Ephapax linear types), which already targets mobile (Phase 5: iOS/Android). Open question Welcome to neurophone Discussions! #1 resolves to gossamer; the migration target (and the "generated Java shim under src-tauri/gen/android/" plan) should be re-expressed in gossamer's terms, coordinating with the gossamer repo on its Android path.

  2. SPDX clash (open question chore(deps): update reqwest requirement from 0.11 to 0.12 #6): canonical is MPL-2.0. The repo has been reverted to SPDX-License-Identifier: MPL-2.0 uniformly (PMPL was a wrong turn). Use MPL-2.0 headers; no clash remains.

(Tracked on the neurophone side as #83, which now names gossamer.)


Generated by Claude Code

hyperpolymath added a commit that referenced this pull request Jun 6, 2026
## Status

**DRAFT — RFC only. Awaiting owner review BEFORE any bulk conversion.**
No Kotlin deleted, no Gossamer scaffolding generated, no behaviour
change.

Supersedes #96 (was titled "Tauri 2" — owner correction: Gossamer is the
estate target).

## Why

`android/` ships 7 Kotlin files + 3 `*.gradle.kts` files, all banned by
the
Hyperpolymath language policy. Two CI gates permanently red:

- `Check for Banned Languages`
(`.github/workflows/language-policy.yml:87-94`)
- `governance / Language / package anti-pattern policy` (estate-wide)

## What this PR contains

A single document — `docs/migrations/RFC-ANDROID-KOTLIN-TO-RUST.adoc` —
mapping every Kotlin component to its Gossamer replacement and proposing
a 9-PR landing sequence.

## Component mapping (one-line summary)

| Kotlin file | Replacement |
|---|---|
| `MainActivity.kt` | `NeurophoneMainActivity extends GossamerActivity`
|
| `NeurophoneService.kt` | Hand-written Java `Service` shim → JNI into
Rust |
| `BootReceiver.kt` | Hand-written Java `BroadcastReceiver` shim → JNI |
| `NativeLib.kt` | Delete; lives in
`crates/neurophone-android/src/lib.rs` |
| `NeurophoneAppWidget.kt` | Hand-written Java `AppWidgetProvider` shim
|
| `NeurophoneWidgetActions.kt` | Hand-written Java `BroadcastReceiver`
shim |
| `NeurophoneWidgetConfigureActivity.kt` | Java `Activity` shim (or
drop) |
| `*.gradle.kts` | Groovy `*.gradle` (matches Gossamer upstream) |

## Key structural finding

**Gossamer Android is webview-only today.** ROADMAP Phase 3 (Mobile)
lists Android as *Partially Implemented* — only `GossamerActivity` +
`GossamerBridge` exist upstream. The 7 platform-integration surfaces
neurophone needs (service, widget, receivers, sensors, intent dispatch,
prefs, deep-links) have **no upstream Gossamer support and no open
Gossamer issues**.

**Recommendation:** build all 7 downstream in neurophone's own
`android/`
tree as small Java shims that JNI immediately into Rust. Don't block
neurophone on Gossamer upstream PRs. Estimated total shim surface: < 250
LoC of Java vs. current 926 LoC of Kotlin.

## Estate precedent

- `panll` migrated `src-tauri/` → `src-gossamer/` (commit `598d537`,
  ADR-0001 in `b935727`). Webview UI unchanged; swapped `tauri` crate
  for `gossamer-rs`, `tauri.conf.json` for `gossamer.conf.json`,
  `cargo tauri build` for `deno task build` invoking the `gossamer` CLI.
- panll is **desktop only** — its migration did not exercise foreground
  service or home-screen widget surfaces; neurophone will be the first.

## Sub-PR sequence (proposed)

1. **This PR** — RFC only.
2. CI exemption for `android/**/*.java` (coordinated with
`hyperpolymath/standards`).
3. Gossamer scaffolding: `gossamer-rs` workspace dep,
`gossamer.conf.json`,
   `NeurophoneMainActivity` Java shim loading placeholder HTML.
4. Port `NativeLib` Kotlin → `crates/neurophone-android/src/lib.rs`.
5. Port `NeurophoneService` → Java shim + Rust impl.
6. Port `BootReceiver`.
7. Port widget triple (provider / actions / configure).
8. AffineScript UI compiled to JS, loaded by Gossamer webview.
9. Delete legacy Kotlin `android/` tree — both CI gates green.

PRs 2 & 3 sequenced; 4–7 parallelizable after 3; 8 needs 4; 9 gated on
all.

## Open questions for owner

1. **CI exemption scope** — estate-wide via `hyperpolymath/standards`
   or neurophone-local? Linchpin question.
2. **Estate governance** — who owns the cross-repo anti-pattern policy
   callable in standards?
3. **Widget config sacrifice** — acceptable to drop the configure
activity?
4. **Gradle DSL** — Groovy `*.gradle` (matches Gossamer upstream) or
   keep Kotlin `*.gradle.kts` under a separate exemption?
5. **Hardware test plan** — Oppo Reno 13 vs emulator + Termux?
6. **Upstream contribution** — build shims neurophone-local, or factor
   a `gossamer-android-services` companion as we go?

## Constraints honoured

- All new files MPL-2.0 SPDX.
- No new GitHub Actions added.
- No Deno/npm/TypeScript changes.

## Test plan

- [x] RFC document renders as AsciiDoc.
- [ ] Owner reviews component mapping for completeness.
- [ ] Owner picks CI-exemption scope (open Q1).
- [ ] Owner resolves Gradle DSL choice (open Q4).
- [ ] Sub-PR #2 (CI exemption) opens once approved.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant